xsplice: Don't perform multiple operations on same payload once work is scheduled.
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Thu, 28 Apr 2016 17:54:14 +0000 (13:54 -0400)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Fri, 29 Apr 2016 07:59:41 +0000 (03:59 -0400)
commitf9bf994d81031b53191106e78653c3983e8e3536
tree0eb5aab249d345e499a8f2830f13e2c21dce756a
parentc2ce28a772352f35922291564fc65410ba9b5b16
xsplice: Don't perform multiple operations on same payload once work is scheduled.

Currently it is possible to:

1)  xc_xsplice_apply()
     \-> xsplice_action
spin_lock(payload_lock)
             \- schedule_work()
        spin_unlock(payload_lock);

2)  xc_xsplice_unload()
     \-> xsplice_action
spin_lock(payload_lock)
             free_payload(data);
        spin_unlock(payload_lock);

.. all CPUs are quiesced.

3) check_for_xsplice_work()
     \-> apply_payload
        \-> arch_xsplice_apply_jmp
BOOM

The reason is that state is in 'CHECKED' which changes to 'APPLIED'
once check_for_xsplice_work finishes. So we have a race between 1) -> 3)
where one can manipulate the payload.

To guard against this we add a check in xsplice_action to not allow
any actions if schedule_work has been called for this specific payload.

The function 'is_work_scheduled' checks xsplice_work which is safe as:
 - The ->do_work changes to 1 under the payload_lock (which we also hold).
 - The ->do_work changes to 0 when all CPUs are quisced and IRQs have
   been disabled.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reported-and-Tested-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-acked-by: Wei Liu <wei.liu2@citrix.com>
xen/common/xsplice.c